package day1105.third;

import day1105.common.MyUtil;
import day1105.common.Student;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static day1105.common.MyUtil.printLine;

/**
 * @author Mr.ma
 * @since 2022/11/6 18:05
 * stream中常用的方法分为中间操作和终止操作
 * 中间操作：
 *      filter(),map(),sorted(),skip(),limit(),distinct()
 * 终止操作：
 *      forEach(),
 *      collect(),
 *      reduce(),
 *      max(),min(),count(),
 *      findFirst(),findAny(),
 *      allMatch(),anyMatch(),noneMatch
 *
 **/
public class AllTest {
    private static List<Student> studentList;
    public static void cpStudent() {
        studentList = MyUtil.createStudentList();
        studentList.stream().forEach(System.out::println);
    }
    @Test
    public void filterTest(){
        cpStudent();
        printLine("获取一班学生信息");
        studentList.stream().filter(s -> "一班".equals(s.getClazz())).forEach(System.out::println);
    }
    @Test
    public void mapTest(){
        cpStudent();
        printLine("获取学生姓名集合");
        List<String> collect = studentList.stream().map(Student::getName).collect(Collectors.toList());
        System.out.println("collect = " + collect);
    }
    @Test
    public void sortedTest(){
        cpStudent();
        printLine("按年龄升序排列输出");
        studentList.stream().sorted().forEach(System.out::println);
        printLine("按成绩升序排列");
        studentList.stream().sorted((s1,s2) -> s1.getScore().compareTo(s2.getScore())).forEach(System.out::println);
        printLine("按城市排列，城市相同，按年龄排列");
        studentList.stream().sorted(Comparator.comparing(Student::getCity).thenComparing(Student::getAge)).forEach(System.out::println);
    }
    @Test
    public void limitTest(){
        cpStudent();
        printLine("获取前三个学生对象");
        studentList.stream().limit(3).forEach(System.out::println);
    }
    @Test
    public void skipTest(){
        cpStudent();
        printLine("跳过前三个学生对象");
        studentList.stream().skip(3).forEach(System.out::println);
    }
    @Test
    public void distinctTest(){
        cpStudent();
        printLine("获取学生班级信息，并进行去重");
        studentList.stream().map(Student::getClazz).distinct().forEach(System.out::println);
    }
    @Test
    public void maxTest(){
        cpStudent();
        printLine("获取年龄最大的学生对象");
        Student student = studentList.stream().max(Student::compareTo).get();
        System.out.println("student = " + student);
    }
    @Test
    public void minTest(){
        cpStudent();
        printLine("获取倒数第一名的学生对象");
        Student student = studentList.stream().min((s1, s2) -> s1.getScore().compareTo(s2.getScore())).get();
        System.out.println("student = " + student);
    }
    @Test
    public void countTest(){
        cpStudent();
        printLine("获取一班的人数");
        long count = studentList.stream().filter(s -> "一班".equals(s.getName())).count();
        System.out.println("一班人数为： " + count + "人");
    }
    @Test
    public void findTest(){
        cpStudent();
        printLine("获取年龄最小的学生对象");
        Optional<Student> first = studentList.stream().sorted().findFirst();
        System.out.println("first.get() = " + first.get());
        printLine("获取任意一个学生对象");
        Student student = studentList.stream().findAny().get();
        System.out.println("student = " + student);
    }
    @Test
    public void matchTest(){
        cpStudent();
        printLine("判断是否存在大于60的学生");
        boolean b = studentList.stream().anyMatch(x -> x.getAge() > 60);
        if (b){
            System.out.println("老铁，挺住");
        } else {
            System.out.println("不存在");
        }
        printLine("判断是否存在未成年学生");
        boolean b1 = studentList.stream().allMatch(x -> x.getAge() >= 18);
        if (b1){
            System.out.println("车门焊丝，现在发车");
        } else {
            System.out.println("滴，学生卡");
        }
        printLine("判断是否有不及格学生");
        boolean b2 = studentList.stream().noneMatch(x -> x.getScore().compareTo(60.0) < 0);
        if (b2){
            System.out.println("允许奖励一次自己");
        } else {
            System.out.println("你们使我带过最差的一届");
        }
    }
    @Test
    public void reduceTest(){
        cpStudent();
        printLine("统计各班总成绩");
        // Bad return type in lambda expression: double cannot be converted to Student
        Double aDouble = studentList.stream().filter(x -> "一班".equals(x.getClazz())).map(Student::getScore).reduce(Double::sum).get();
        System.out.println("一班总成绩为：" + aDouble);
        Double reduce = studentList.stream().filter(x -> "二班".equals(x.getClazz())).map(Student::getScore).reduce(0.0, Double::sum);
        System.out.println("一班总成绩为：" + reduce);
    }
    @Test
    public void collectTest(){
        cpStudent();
        printLine("统计各班的平均成绩");
        Double collect = studentList.stream().filter(x -> "一班".equals(x.getClazz()))
                .collect(Collectors.averagingDouble(Student::getScore));
        System.out.println("一班平均成绩为：" + collect);
        printLine("使用groupingBy实现统计各班的平均成绩");
        Map<String, Double> collect1 = studentList.stream().collect(Collectors.groupingBy(Student::getClazz, Collectors.averagingDouble(Student::getScore)));
        collect1.forEach((key,value) -> System.out.println(key + "平均成绩为：" + value));
    }
    @Test
    public void concatTest(){
        cpStudent();
        printLine();
        String[] arrStr = new String[]{"hello","world"};
        Arrays.stream(arrStr).forEach(System.out::println);
        printLine("map实现数组中字符串拆分去重");
        List<String[]> collect = Arrays.stream(arrStr).map(x -> x.split("")).collect(Collectors.toList());
        List<String> collect1 = Stream.concat(Arrays.stream(collect.get(0)), Arrays.stream(collect.get(1))).distinct().collect(Collectors.toList());
        System.out.println("collect1 = " + collect1);
        printLine("flatMap实现数组中字符串拆分去重");
        List<Object> collect2 = Stream.of(arrStr).map(x -> x.split("")).flatMap(Arrays::stream).distinct().collect(Collectors.toList());
        System.out.println("collect2 = " + collect2);
    }
}
